// callback to receive raw RTP media packets from the media engine. // this callback can be registered on a per phone line basis. // // From RFC2833: // // 3.10 DTMF Events // // Table 1 summarizes the DTMF-related named events within the // telephone-event payload format. // // Event encoding (decimal) // _________________________ // 0--9 0--9 // * 10 // # 11 // A--D 12--15 // Flash 16 // // Table 1: DTMF named events // // void __stdcall DtmfRawRtpCallback(RAW_RTP_DATA *pRawRtpData) { CVPhoneDlg *pDlg; int NumDtmfPayloads; int cnt; BYTE DTMF_Event; BOOL DTMF_E; BOOL DTMF_R; BYTE DTMF_Volume; UINT DTMF_Duration; UINT *pDtmfPayload; UINT DtmfPayload; // get the app specified instance data. pDlg = (CVPhoneDlg *)pRawRtpData->pUserData; if(pRawRtpData->TransmittingPacket) { // this RTP data is being transmitted. // do nothing. // // if you want to transmit RFC2833 DTMF packets, // your source code can modify the ready-to-be-transmitted // RTP data at this point. // } else { // this RTP data is being received. // // look for RFC2833 DTMF payloads // // generally (99.9999% of the time) the payload type is 101 for // out of band DTMF. This however depends on how the SIP call // enpoints are actually configured. if((pRawRtpData->pRtpHeader->PayloadType == 101) || (pRawRtpData->pRtpHeader->PayloadType == 127) // Avaya phones. ) { // this is "out of band" DTMF! // // the payload data is 4 bytes as per RFC 2833 (see section 3.5) // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | event |E|R| volume | duration | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Figure 1: Payload Format for Named Events // // access the DTMF payload as a 32 bit value. pDtmfPayload = (UINT *)pRawRtpData->pSampleBuffer; NumDtmfPayloads = (pRawRtpData->RtpPacketLengthInBytes - pRawRtpData->RtpHeaderLengthInBytes)/4; for(cnt=0;cnt> 24; // the "end" bit. DTMF_E = (DtmfPayload >> 23) & 0x01; // reserved bit - not used. DTMF_R = (DtmfPayload >> 22) & 0x01; // the DTMF power level (volume). DTMF_Volume = (DtmfPayload >> 16) & 0x3f; // tone duration. DTMF_Duration = DtmfPayload & 0xffff; // now do something with the DTMF data we have. // // Notes: // // 1) // The RTP header TimeStamp will be the same for // all received DTMF RTP payloads for the DTMF digit being // received. Use this fact to distinguish when new DTMF // digits are being received. New DTMF digits will have a // new RTP header TimeStamp. // // pRawRtpData->pRtpHeader->TimeStamp // // 2) // When the DTMF digit terminates, the last few received DTMF // RTP payloads will have the DTMF_E bit set indicating the // end of DTMF. However, be careful using this. if your network // connection gets unplugged while the other side sends the end // packets, you could miss them. DTMF RTP payloads generally are // received at the codec rate or possiblt every 50Ms as per the // RFC. Your software should implement a timeout feature for all // received RTP DTMF digits so that a network connection failure // will not affect your ability to detect completion of DTMF // signals. // } // tell the media enigne to ignore this RTP DTMF packet. // if you don't do this, the RTP receiver logic will try // to interpret the DTMF payload as encoded audio. pRawRtpData->ProcessRtpPacket = FALSE; } } }